package cm.tl.pms.util;

import cn.hutool.core.convert.Convert;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: lwp
 * @date: 2024/5/20 16:22
 * @description
 * @version: 1.0
 */
@Slf4j
public class NumberUtils {

    /**
     * 将给定的数字与单位一起格式化
     *
     * @param number 要格式化的数字
     * @return 格式化后的数字与单位
     * @throws NumberFormatException 如果输入的数字不是有效的double类型
     */
    public static String formatNumberWithUnit(Object number) {
        try {
            BigDecimal parsedNumber = Convert.toBigDecimal(number);
            return formatNumberWithUnit(parsedNumber);
        } catch (NumberFormatException e) {
            return "0";
        }
    }

    /**
     * 格式化数字和单位的字符串表示
     *
     * @param number 要格式化的数字
     * @return 格式化后的字符串
     */
    public static String formatNumberWithUnit(BigDecimal number) {
        boolean isNegative = number.compareTo(BigDecimal.ZERO) < 0;
        BigDecimal absoluteNumber = number.abs();

        String formattedNumber;
        if (absoluteNumber.compareTo(new BigDecimal("100000000")) >= 0) {
            formattedNumber = formatNumberWithSpecificUnit(absoluteNumber, new BigDecimal("100000000"), "亿");
        } else if (absoluteNumber.compareTo(new BigDecimal("10000")) >= 0) {
            formattedNumber = formatNumberWithSpecificUnit(absoluteNumber, new BigDecimal("10000"), "万");
        } else {
            formattedNumber = absoluteNumber.setScale(2, RoundingMode.HALF_UP).toString();
        }
        return formatAmount(isNegative ? "-" + formattedNumber : formattedNumber);
        // return isNegative ? "-" + formattedNumber : formattedNumber;
    }

    /**
     * 格式化带有特定单位的数字为字符串
     *
     * @param number   需要格式化的数字
     * @param unit     相对单位
     * @param unitName 相对单位名称
     * @return 格式化后的字符串
     */
    private static String formatNumberWithSpecificUnit(BigDecimal number, BigDecimal unit, String unitName) {
        BigDecimal result = number.divide(unit);
        return result.setScale(2, BigDecimal.ROUND_HALF_UP) + unitName;
    }


    /**
     * 格式化指定单位的数字
     *
     * @param number   需要格式化的数字
     * @param unit     单位
     * @param unitName 单位名称
     * @return 格式化后的字符串
     */
    private static String formatNumberWithSpecificUnit(double number, double unit, String unitName) {
        // 将输入的数值除以单位，得到换算后的结果
        double result = number / unit;
        // 使用String的format方法，将结果保留两位小数，并附加单位名称
        return String.format("%.2f%s", result, unitName);
    }


    public static String formatNumberWithUnit(String number, int unit, String unitName) {
        double parsedNumber = Double.parseDouble(number);
        // 将输入的数值除以单位，得到换算后的结果
        double result = parsedNumber / unit;
        // 使用String的format方法，将结果保留两位小数，并附加单位名称
        return String.format("%.2f%s", result, unitName);
    }

    private final static Pattern pattern = Pattern.compile("(-?\\d+(\\.\\d+)?)(万|亿|万亿|百万|百亿)?");

    /**
     * 标题：格式化金额
     * <p>
     * 描述：该方法用于将金额格式化为指定格式的字符串。
     * <p>
     * 参数：
     * - amount：要格式化的金额，类型为double。
     * <p>
     * 返回值：
     * - 格式化后的金额字符串，类型为String。
     */
    public static String formatAmount(Object amount) {
        String amountStr = "0.00";
        try {
            // 处理带有单位的字符串
            amountStr = Convert.toStr(amount);
            Matcher matcher = pattern.matcher(amountStr);

            if (matcher.matches()) {
                String numberPart = matcher.group(1);
                String unitPart = matcher.group(3);

                // 格式化数字部分
                DecimalFormat df = new DecimalFormat("#,###.00");
                String formattedNumber = df.format(new BigDecimal(numberPart));

                // 检查是否为 ".00"，如果是则替换为 "0.00"
                if (formattedNumber.equals(".00")) {
                    formattedNumber = "0.00";
                }

                // 返回带单位的格式化结果
                return formattedNumber + (unitPart != null ? unitPart : "");
            }

            // 处理纯数字字符串
            BigDecimal bigDecimalAmount = Convert.toBigDecimal(amount);
            if (bigDecimalAmount != null) {
                DecimalFormat df = new DecimalFormat("#,###.00");
                String formattedNumber = df.format(bigDecimalAmount);

                // 检查是否为 ".00"，如果是则替换为 "0.00"
                if (formattedNumber.equals(".00")) {
                    formattedNumber = "0.00";
                }
                return formattedNumber;
            }
        } catch (Exception e) {
            log.error("转化格式报错！amount = {}", amount, e);
        }
        // 处理失败了，返回原值
        return amountStr;
    }


    /**
     * 解析带单位的数字字符串并返回浮点数
     *
     * @param numberWithUnit 带单位的数字字符串，例如"12亿"
     * @return 解析后的浮点数，去除了单位后的数字
     */
    public static String parseNumberWithUnit(String numberWithUnit) {
        double number;
        String unit;

        if (numberWithUnit.contains("亿")) {
            unit = "亿";
            number = Double.parseDouble(numberWithUnit.replace(unit, "").trim());
            number *= 1_0000_0000;
        } else if (numberWithUnit.contains("万")) {
            unit = "万";
            number = Double.parseDouble(numberWithUnit.replace(unit, "").trim());
            number *= 1_0000;
        } else {
            number = Double.parseDouble(numberWithUnit);
        }

        return String.format("%.0f", number);
    }


    /**
     * 将字符串表示的数字转换为以万为单位并保留两位小数的字符串。
     * 如果传入的是负数，也按照相同的规则处理。
     *
     * @param numberStr 字符串表示的数字
     * @return 以万为单位并保留两位小数的字符串
     */
    public static String convertToWan(String numberStr) {
        try {
            double number = Double.parseDouble(numberStr);
            double wan = number / 10000.0;
            return String.format("%.2f", wan);
        } catch (NumberFormatException e) {
            // 如果输入不是有效的数字，返回原字符串或者错误信息
            return "0.00";
        }
    }

    /**
     * 如果传入的数字小于100，则按0.01处理，否则保持不变。
     * 此方法用于处理特殊的小数情况。
     *
     * @param number 字符串表示的数字
     * @return 处理后的数字字符串
     */
    public static double handleLessThanHundred(double number) {
        try {
            if (number < 100) {
                return 0.01;
            } else {
                return number;
            }
        } catch (NumberFormatException e) {
            // 如果输入不是有效的数字，返回原字符串或者错误信息
            return 0.00;
        }
    }


    public static void main(String[] args) {
        String[] numbers = {"5531600.00", "0.00", "18337.13", "-50000000.00", "99.99", "5000万", "1.2万亿", "0"};
        for (String numberStr : numbers) {
            System.out.println(formatAmount(numberStr));
        }
    }


}